package common.utils.wechat;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import common.AppConst;
import common.utils.HttpRequestUtil;
import javax.servlet.http.HttpServletRequest;


/**
 * 公众平台通用接口工具类
 *
 * @author kinfeng 
 * @date 2015-02-27
 */
public class WxConfigUtil {
	private static Logger logger = Logger.getLogger(WxConfigUtil.class);
	// 生成签名的随机串
	public final static String nonce_str = UUID.randomUUID().toString().substring(0,15);
	public final static Long timestamp = System.currentTimeMillis() / 1000;
	// 获取access_token的接口地址（GET） 限2000（次/天）
	public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	// 获取jsapi_ticket的接口地址（GET） 限2000（次/天）
	public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
	//获取授权CODE
	public final static String get_code_url = "https://open.weixin.qq.com/connect/oauth/authorize?appid=APPID&redirect_uri=url&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
    //静默授权
	public final static String get_openId_url ="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
	
	// 缓存添加的时间
	public static String cacheAddTime = null;
	// token,ticket缓存
	public static Map<String, AccessToken> TOKEN_TICKET_CACHE = new HashMap<String, AccessToken>();
	// ticket对应的key
	private static final String TICKET = "ticket";
	


	/**
	 * 获取access_token
	 *
	 * @param appid
	 *            凭证
	 * @param appsecret
	 *            密钥
	 * @return
	 */
	public static AccessToken getAccessToken(String appid, String appsecret, long currentTime) {
		AccessToken accessToken = null;
		logger.info("==========缓存中token不存在或已过期===============");
		String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
		JSONObject jsonObject = HttpRequestUtil.httpRequest(requestUrl, "GET", null);
		// 如果请求成功
		if (null != jsonObject) {
			accessToken = new AccessToken();
			accessToken.setToken(jsonObject.getString("access_token"));
			accessToken.setExpiresIn(jsonObject.getInt("expires_in"));// 正常过期时间是7200秒，此处设置3600秒读取一次
			logger.info("==========tocket缓存过期时间为:" + accessToken.getExpiresIn() * 1000 + "毫秒");
			accessToken.setAddTime(currentTime);
		}
		return accessToken;
	}
	/**
	 * 获取openId
	 *
	 * @param appid
	 *            凭证
	 * @param code
	 *            密钥
	 * @return
	 */
	private static String getOpenId(String appid,String secret, String code) {
		String requestUrl = get_openId_url.replace("APPID", appid).replace("CODE", code).replace("SECRET", secret);
		JSONObject jsonObject = HttpRequestUtil.httpRequest(requestUrl, "GET", null);
		// 如果请求成功
		if (null != jsonObject) {
			String openId = jsonObject.getString("openid");
			return openId;
		}
		return null;
	}	/**
	 * 获取openId
	 *
	 * @param appid
	 *            凭证
	 * @param code
	 *            密钥
	 * @return
	 */
	public static String getCode(String url) {
		String requestUrl = getCodeUrl(url);
		JSONObject jsonObject = HttpRequestUtil.httpRequest(requestUrl, "post", null);
		// 如果请求成功
		if (null != jsonObject) {
			String code = jsonObject.getString("code");
			return code;
		}
		return null;
	}
	/**
	 * 获取ticket
	 *
	 * @param token
	 *
	 * @return
	 */
	private static AccessToken getTicket(String token, long currentTime) {
		AccessToken accessToken = null;
		String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);
		JSONObject jsonObject = HttpRequestUtil.httpRequest(requestUrl, "GET", null);
		// 如果请求成功
		if (null != jsonObject) {
			accessToken = new AccessToken();
			accessToken.setTicket(jsonObject.getString("ticket"));
			accessToken.setExpiresIn(jsonObject.getInt("expires_in") / 2);// 正常过期时间是7200秒，此处设置3600秒读取一次
			accessToken.setAddTime(currentTime);
		}
		return accessToken;
	}

	

	/**
	 * 
	 * @param request
	 * @param url
	 * @return
	 */
    
    public static  Map<String, Object> getWXConfigMap(HttpServletRequest request,String url){
        AccessToken token = getAccessToken(AppConst.APPID, AppConst.SECRET, timestamp);
        Map<String,Object> map = getJsSignMap(getTicket(token.getToken(),timestamp).getTicket(),url);
        return map;
    }
    /**
     * 获取openid
     * @param request
     * @return
     */
    public static  String getWXUserOpenId(HttpServletRequest request,String url){
    	
    	String code= getCode(url);
        String openId = getOpenId(AppConst.APPID, AppConst.SECRET, code);
        return openId;
    }
    /**
     * 获取jsapi相关参数map
     * @param jsapi_ticket
     * @param url
     * @return
     */
    public static Map<String, Object> getJsSignMap(String jsapi_ticket, String url) {
        Map<String, Object> map = new HashMap<String, Object>();


        //注意这里参数名必须全部小写，且必须有序
        String s = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;
        String signature = null;
        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(s.getBytes("UTF-8"));
            signature = WXSign.byteToHex(crypt.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
        	logger.error("WxConfigUtil getJsSignMap：获取微信公众号jsapi失败！"+e);
        }
        catch (UnsupportedEncodingException e)
        {
        	logger.error("WxConfigUtil getJsSignMap：获取微信公众号jsapi失败！"+e);
        }

        map.put("url", url);
        map.put("appid", AppConst.APPID);
        map.put("jsapi_ticket", jsapi_ticket);
        map.put("nonceStr", nonce_str);
        map.put("timestamp", timestamp.toString());
        map.put("signature", signature);

        return map;
    }
	public static String getCodeUrl(String url){
		String codeUrl = get_code_url.replace("APPID", AppConst.APPID).replace("url", url);
		return codeUrl;
	}
	/**
	 * 获取URL
	 * @param request
	 * @return
	 */
	public static String getRequestURL(HttpServletRequest request) {
	    if (request == null) {
	        return "";
	    }
	    String url = request.getRequestURL().toString();

	    if (request.getQueryString() != null && !"".equals(request.getQueryString()) && !"null".equals(request.getQueryString()) ) {
	        url = url + "?" + request.getQueryString();
	    }

	    return url;
	}
	
	
}